根據證交所統計,在 1990 年代,散戶成交比重佔整體市場九成以上;自 2010 年起,法人成交比重皆穩定佔三至四成。現在的臺股是法人主導的時代,比起散戶,法人擁有龐大的資金部位,掌握消息的速度也遠勝於一般投資人,因此三大法人能夠更有效地研判市場行情走勢。
我們在收看財經新聞或閱讀報章雜誌時,經常會看到「三大法人」,究竟什麼是三大法人?在法律上的「人」可分為「自然人」和「法人」。每個生物學意義上的人都是指自然人;法人則是在法律上享有權利義務的組織團體。在股市中,一般投資人就是自然人,也就是散戶;法人則是機構投資者。在臺灣證券市場,外資、投信、自營商 稱作三大法人。
「買賣超」是指買進金額與賣出金額的差額,當買進金額大於賣出金額時,稱為「買超」;當賣出金額大於買進金額時,稱為「賣超」。
在三大法人中,外資的資金最雄厚,在集中市場往往佔了三成以上的買賣金額,且買賣的標的主要都是大型權值股,所以外資在臺股的連續買超或買超,容易帶出大盤的波段走勢。
Source:臺灣證券交易所
下表整理出 2022 年初至 8 月 31 日,外資買賣超金額前五名,可以發現外資的大買或大賣容易造成加權指數的大漲或大跌。
日期 | 加權指數漲跌 | 漲跌幅 | 外資買超金額 | 日期 | 加權指數漲跌 | 漲跌幅 | 外資賣超金額 |
---|---|---|---|---|---|---|---|
2022-03-17 | 507.39 | 3.00% | 448.17 億元 | 2022-03-07 | -557.83 | -3.15% | -823.71 億元 |
2022-05-30 | 344.40 | 2.12% | 275.80 億元 | 2022-03-15 | -336.98 | -1.95% | -538.42 億元 |
2022-01-04 | 255.84 | 1.40% | 257.05 億元 | 2022-02-24 | -461.18 | -2.55% | -534.50 億元 |
2022-08-05 | 333.84 | 2.27% | 247.26 億元 | 2022-02-25 | 57.63 | 0.33% | -510.30 億元 |
2022-05-31 | 197.15 | 1.19% | 232.56 億元 | 2022-06-13 | -389.14 | -2.36% | -480.28 億元 |
Source:臺灣證券交易所
上表中,唯一的例外是 2022 年 2 月 25 日,因為這天適逢 MSCI 指數季度調整,主要是來自外資被動型基金調降臺股權重的賣盤。根據經驗, MSCI 調整外資大都在最後一盤執行買賣,所以容易發生「爆量甩尾」的現象,不過也因如此,若當日無特殊事件,這種因指數調整引起的外資買賣盤,在盤中比較不會造成劇烈波動。
MSCI(Morgan Stanley Capital International)是國際知名的指數編制公司,與臺股相關的三大指數為「MSCI全球市場指數」、「MSCI全球新興市場指數」、「MSCI亞洲除日本指數」。當臺股被調升權重時,就會有外資被動基金的買盤;而臺股被調降權重時,則會有外資被動基金的賣盤。MSCI 指數會在每年 2、5、8、11 月中公布調整權重,並於該月月底底生效。
除了三大法人外,政府基金也是不可忽視的力量,因此常被稱為第四大法人。根據證交所資料統計,自 2022 年初至 8 月 31 日止,外資累計賣超金額已超過 1 兆元,加權指數也從最高 18619.61 點一路下探。在 2022 年 7 月 12 日,加權指數大跌 389.12 點,收 13950.62 點,當日收盤後政府宣布國安基金進場。從國安基金進場至 8 月 31 日止,外資仍然賣超大於買超,但在這一個多月期間,加權指數不再破底,顯示國安基金確實有達到穩定盤勢的作用。
Source:臺灣證券交易所
由於在交易所沒有辦法查詢政府基金進出,所以市場上有一些資訊廠商會提供 八大公股行庫(臺灣銀行、土地銀行、合作金庫、第一銀行、華南銀行、彰化銀行、兆豐銀行、台灣企銀)買賣超數據,主要是統計八大公股行庫券商的分點進出,作為政府基金買賣判斷的依據。不過需要注意的是,任何有資格開戶的投資人都可以到八大公股行庫券商開立證券戶,所以這個數據不代表政府基金實際的進出狀況,僅能作為參考。
在三大法人中,外資買賣超對大盤指數的走勢有決定性的影響,因此在三大法人我們會格外關注外資的動向。
在證交所網站的 三大法人買賣金額統計表 頁面,可以查詢集中市場三大法人買賣金額統計日報表、週報表及月報表。
證交所首頁 > 交易資訊 > 三大法人 > 三大法人買賣金額統計表
在「三大法人買賣金額統計表」頁面選取「日報表」以及「日期」按下「查詢」後,就會列出該日的三大法人買賣金額統計表。
點擊「列印 / HTML」連結,瀏覽器會開新分頁將資訊輸出成可列印的 HTML 頁面。假設資料日期為「民國 111 年 07 月 01 日」,我們會得到以下 URL:
https://www.twse.com.tw/fund/BFI82U?response=html&dayDate=&weekDate=&monthDate=&type=day
以上 URL 可設定的參數如下:
response
:回應資料的格式。指定 html
輸出 HTML 文件;改為 csv
可以另存 CSV 檔案;設定成 json
或不指定則回應 JSON 格式資料。dayDate
:日報表日期。接受的日期格式為 yyyyMMdd
,如 20220701
。weekDate
:週報表日期,日期為當週第一天。接受的日期格式為 yyyyMMdd
,如 20220627
。monthDate
:月報表日期,日期為當月第一天。接受的日期格式為 yyyyMMdd
,如 20220701
。type
:報表類型。day
為日報表;week
為週報表;month
為月報表。我們將 URL 查詢參數改為 response=json&dayDate=20220701&type=day
,證交所就會以 JSON 格式資料回應 2022 年 7 月 1 日的三大法人買賣金額統計:
{
"stat": "OK",
"title": "111年07月01日 三大法人買賣金額統計表",
"fields": [
"單位名稱",
"買進金額",
"賣出金額",
"買賣差額"
],
"date": "20220701",
"data": [
[
"自營商(自行買賣)",
"9,244,024,457",
"4,625,853,798",
"4,618,170,659"
],
[
"自營商(避險)",
"11,198,410,934",
"11,602,781,673",
"-404,370,739"
],
[
"投信",
"4,911,910,560",
"3,492,825,917",
"1,419,084,643"
],
[
"外資及陸資(不含外資自營商)",
"90,214,449,445",
"102,070,998,550",
"-11,856,549,105"
],
[
"外資自營商",
"14,961,580",
"25,373,730",
"-10,412,150"
],
[
"合計",
"115,568,795,396",
"121,792,459,938",
"-6,223,664,542"
]
],
"params": {
"response": "json",
"dayDate": "20220701",
"weekDate": "20220627",
"monthDate": "20220701",
"type": "day",
"controller": "fund",
"format": null,
"action": "BFI82U",
"lang": "zh"
},
"notes": [
"自營商表示證券自營商專戶。",
"投信表示本國投資信託基金。",
"外資及陸資表示依「華僑及外國人投資證券管理辦法」及「大陸地區投資人來臺從事證券投資及期貨交易管理辦法」辦理登記等投資人。",
"因外資自營商買賣金額已計入自營商買賣金額,故不納入三大法人買賣金額之合計數計算。",
"本統計資訊含一般、零股、盤後定價、鉅額,不含拍賣、標購。",
"本資訊以當日原始成交情形統計,不以證券商申報錯帳、更正帳號等調整後資料統計。",
"外幣成交值係以本公司當日下午3時30分公告匯率換算後加入成交金額。<br>公告匯率請參考本公司首頁>產品與服務>交易系統>雙幣ETF專區>代號對應及每日公告匯率。"
]
}
在我們的專案中,開啟 src/scraper/twse-scraper.service.ts
檔案,在 TwseScraperService
實作 fetchInstInvestorsTrades()
方法,取得集中市場三大法人買賣金額:
import * as cheerio from 'cheerio';
import * as iconv from 'iconv-lite';
import * as numeral from 'numeral';
import { DateTime } from 'luxon';
import { Injectable } from '@nestjs/common';
import { HttpService } from '@nestjs/axios';
import { firstValueFrom } from 'rxjs';
@Injectable()
export class TwseScraperService {
constructor(private httpService: HttpService) {}
...
async fetchInstInvestorsTrades(date: string) {
// 將 `date` 轉換成 `yyyyMMdd` 格式
const formattedDate = DateTime.fromISO(date).toFormat('yyyyMMdd');
// 建立 URL 查詢參數
const query = new URLSearchParams({
response: 'json', // 指定回應格式為 JSON
dayDate: formattedDate, // 指定資料日期
type: 'day', // 指定輸出日報表
});
const url = `https://www.twse.com.tw/fund/BFI82U?${query}`;
// 取得回應資料
const responseData = await firstValueFrom(this.httpService.get(url))
.then(response => (response.data.stat === 'OK') && response.data);
// 若該日期非交易日或尚無成交資訊則回傳 null
if (!responseData) return null;
// 整理回應資料
const raw = responseData.data
.map(data => data.slice(1)).flat() // 取出買賣金額並減少一層陣列嵌套
.map(data => numeral(data).value() || +data); // 轉為數字格式
const [
dealersProprietaryBuy, // 自營商(自行買賣)買進金額
dealersProprietarySell, // 自營商(自行買賣)賣出金額
dealersProprietaryNetBuySell, // 自營商(自行買賣)買賣超
dealersHedgeBuy, // 自營商(避險)買進金額
dealersHedgeSell, // 自營商(避險)賣出金額
dealersHedgeNetBuySell, // 自營商(避險)買賣超
sitcBuy, // 投信買進金額
sitcSell, // 投信賣出金額
sitcNetBuySell, // 投信買賣超
foreignDealersExcludedBuy, // 外資及陸資(不含外資自營商)買進金額
foreignDealersExcludedSell, // 外資及陸資(不含外資自營商)賣出金額
foreignDealersExcludedNetBuySell, // 外資及陸資(不含外資自營商)買賣超
foreignDealersBuy, // 外資自營商買進金額
foreignDealersSell, // 外資自營商賣出金額
foreignDealersNetBuySell, // 外資自營商買賣超
] = raw;
// 計算外資合計買進金額
const foreignInvestorsBuy = foreignDealersExcludedBuy + foreignDealersBuy;
// 外資合計賣出金額
const foreignInvestorsSell = foreignDealersExcludedSell + foreignDealersSell;
// 計算外資合計買賣超
const foreignInvestorsNetBuySell = foreignDealersExcludedNetBuySell + foreignDealersNetBuySell;
// 計算自營商合計買進金額
const dealersBuy = dealersProprietaryBuy + dealersHedgeBuy;
// 計算自營商合計賣出金額
const dealersSell = dealersProprietarySell + dealersHedgeSell;
// 計算自營商合計買賣超
const dealersNetBuySell = dealersProprietaryNetBuySell + dealersHedgeNetBuySell;
return {
date,
foreignDealersExcludedBuy,
foreignDealersExcludedSell,
foreignDealersExcludedNetBuySell,
foreignDealersBuy,
foreignDealersSell,
foreignDealersNetBuySell,
foreignInvestorsBuy,
foreignInvestorsSell,
foreignInvestorsNetBuySell,
sitcBuy,
sitcSell,
sitcNetBuySell,
dealersProprietaryBuy,
dealersProprietarySell,
dealersProprietaryNetBuySell,
dealersHedgeBuy,
dealersHedgeSell,
dealersHedgeNetBuySell,
dealersBuy,
dealersSell,
dealersNetBuySell,
};
}
}
在 fetchInstInvestorsTrades()
方法中,需要指定 date
參數,表示要取得三大法人買賣金額的日期。我們定義回傳的物件欄位包含如下:
date
:日期foreignDealersExcludedBuy
:外資及陸資(不含外資自營商)買進金額foreignDealersExcludedSell
:外資及陸資(不含外資自營商)賣出金額foreignDealersExcludedNetBuySell
:外資及陸資(不含外資自營商)買賣超foreignDealersBuy
:外資自營商買進金額foreignDealersSell
:外資自營商賣出金額foreignDealersNetBuySell
:外資自營商買賣超foreignInvestorsBuy
:外資合計買進金額foreignInvestorsSell
:外資合計賣出金額foreignInvestorsNetBuySell
:外資合計買賣超sitcBuy
:投信買進金額sitcSell
:投信賣出金額sitcNetBuySell
:投信買賣超dealersProprietaryBuy
:自營商(自行買賣)買進金額dealersProprietarySell
:自營商(自行買賣)賣出金額dealersProprietaryNetBuySell
:自營商(自行買賣)買賣超dealersHedgeBuy
:自營商(避險)買進金額dealersHedgeSell
:自營商(避險)賣出金額dealersHedgeNetBuySell
:自營商(避險)買賣超dealersBuy
:自營商合計買進金額dealersSell
:自營商合計賣出金額dealersNetBuySell
:自營商合計買賣超完成後,我們只要呼叫 TwseScraperService
的 fetchInstInvestorsTrades()
方法,就可以按日期取得集中市場三大法人買賣金額。以日期 2022-07-01
為例:
{
date: '2022-07-01',
foreignDealersExcludedBuy: 90214449445,
foreignDealersExcludedSell: 102070998550,
foreignDealersExcludedNetBuySell: -11856549105,
foreignDealersBuy: 14961580,
foreignDealersSell: 25373730,
foreignDealersNetBuySell: -10412150,
foreignInvestorsBuy: 90229411025,
foreignInvestorsSell: 102096372280,
foreignInvestorsNetBuySell: -11866961255,
sitcBuy: 4911910560,
sitcSell: 3492825917,
sitcNetBuySell: 1419084643,
dealersProprietaryBuy: 9244024457,
dealersProprietarySell: 4625853798,
dealersProprietaryNetBuySell: 4618170659,
dealersHedgeBuy: 11198410934,
dealersHedgeSell: 11602781673,
dealersHedgeNetBuySell: -404370739,
dealersBuy: 20442435391,
dealersSell: 16228635471,
dealersNetBuySell: 4213799920
}
在櫃買中心網站的 三大法人買賣金額彙總表 頁面,可以查詢櫃買市場三大法人買賣金額統計的日報表、周報表、月報表及年報表。
櫃買中心首頁 > 上櫃 > 三大法人 > 三大法人買賣金額彙總表
在「三大法人買賣金額彙總表」頁面選取日報表頁籤,選擇「上櫃股票」和「資料日期」後,就會列出該日的三大法人買賣金額彙總表。
點擊「列印/匯出HTML」連結,瀏覽器會開新分頁將資訊輸出成可列印的 HTML 頁面。假設資料日期為「111/07/01」,我們會得到以下 URL:
https://www.tpex.org.tw/web/stock/3insti/3insti_summary/3itrdsum_result.php?l=zh-tw&t=D&p=1&d=111/07/01&o=htm
以上 URL 可設定的參數如下:
l
:輸出資料的語系。zh-tw
為正體中文;en-us
為英文。t
:輸出報表類型。D
為日報表;W
為週報表;D
為月報表;Y
為年報表。p
:統計範圍。0
為上櫃有價證券;1
為上櫃股票。d
:資料日期。接受 民國年/月/日
的日期格式。需要注意,若 l
參數指定為 en-us
,則 d
參數需改成 西元年/月/日
的日期格式。o
:資料輸出的格式。指定 htm
表示輸出 HTML 文件;改為 csv
可以另存 CSV 檔案;設定成 json
或不指定則回應 JSON 格式資料。我們將 URL 查詢參數改為 l=zh-tw&t=D&p=1&d=111/07/01&o=json
,櫃買中心就會以 JSON 格式資料回應 2022 年 7 月 1 日上櫃股票三大法人日彙總交易資訊:
{
"reportTitle": "111年07月01日上櫃股票三大法人日彙總交易資訊",
"reportDate": "111/07/01",
"iTotalRecords": 8,
"csvContentNote": "本統計資訊含等價、零股、盤後定價、鉅額交易,不含標購。",
"csvFileTime": "1934",
"aaData": [
[
"外資及陸資合計",
"17,118,561,407",
"15,962,798,357",
"1,155,763,050"
],
[
" 外資及陸資(不含自營商)",
"17,118,561,407",
"15,962,798,357",
"1,155,763,050"
],
[
" 外資自營商",
"0",
"0",
"0"
],
[
"投信",
"415,300,400",
"1,524,110,550",
"-1,108,810,150"
],
[
"自營商合計",
"1,028,395,980",
"1,499,298,461",
"-470,902,481"
],
[
" 自營商(自行買賣)",
"597,195,811",
"961,369,837",
"-364,174,026"
],
[
" 自營商(避險)",
"431,200,169",
"537,928,624",
"-106,728,455"
],
[
"三大法人合計*",
"18,562,257,787",
"18,986,207,368",
"-423,949,581"
]
]
}
開啟 src/scraper/tpex-scraper.service.ts
檔案,在 TpexScraperService
實作 fetchInstInvestorsTrades()
方法,取得櫃買市場三大法人買賣金額:
import * as numeral from 'numeral';
import { DateTime } from 'luxon';
import { Injectable } from '@nestjs/common';
import { HttpService } from '@nestjs/axios';
import { firstValueFrom } from 'rxjs';
@Injectable()
export class TpexScraperService {
constructor(private httpService: HttpService) {}
async fetchInstInvestorsTrades(date: string) {
// `date` 轉換成 `民國年/MM/dd` 格式
const dt = DateTime.fromISO(date);
const year = dt.get('year') - 1911;
const formattedDate = `${year}/${dt.toFormat('MM/dd')}`;
// 建立 URL 查詢參數
const query = new URLSearchParams({
l: 'zh-tw', // 指定語系為正體中文
t: 'D', // 指定輸出日報表
d: formattedDate, // 指定資料日期
o: 'json', // 指定回應格式為 JSON
});
const url = `https://www.tpex.org.tw/web/stock/3insti/3insti_summary/3itrdsum_result.php?${query}`;
// 取得回應資料
const responseData = await firstValueFrom(this.httpService.get(url))
.then(response => (response.data.iTotalRecords > 0) && response.data);
// 若該日期非交易日或尚無成交資訊則回傳 null
if (!responseData) return null;
// 整理回應資料
const raw = responseData.aaData
.map(data => data.slice(1)).flat() // 取買賣金額並減少一層陣列嵌套
.map(data => numeral(data).value() || +data); // 轉為數字格式
const [
foreignInvestorsBuy, // 外資及陸資合計買進金額
foreignInvestorsSell, // 外資及陸資合計賣出金額
foreignInvestorsNetBuySell, // 外資及陸資合計買賣超
foreignDealersExcludedBuy, // 外資及陸資(不含外資自營商)買進金額
foreignDealersExcludedSell, // 外資及陸資(不含外資自營商)賣出金額
foreignDealersExcludedNetBuySell, // 外資及陸資(不含外資自營商)買賣超
foreignDealersBuy, // 外資自營商買進金額
foreignDealersSell, // 外資自營商賣出金額
foreignDealersNetBuySell, // 外資自營商買賣超
sitcBuy, // 投信買進金額
sitcSell, // 投信賣出金額
sitcNetBuySell, // 投信買賣超
dealersBuy, // 自營商合計買進金額
dealersSell, // 自營商合計賣出金額
dealersNetBuySell, // 自營商合計買賣超
dealersProprietaryBuy, // 自營商(自行買賣)買進金額
dealersProprietarySell, // 自營商(自行買賣)賣出金額
dealersProprietaryNetBuySell, // 自營商(自行買賣)買賣超
dealersHedgeBuy, // 自營商(避險)買進金額
dealersHedgeSell, // 自營商(避險)賣出金額
dealersHedgeNetBuySell, // 自營商(避險)買賣超
] = raw;
return {
date,
foreignDealersExcludedBuy,
foreignDealersExcludedSell,
foreignDealersExcludedNetBuySell,
foreignDealersBuy,
foreignDealersSell,
foreignDealersNetBuySell,
foreignInvestorsBuy,
foreignInvestorsSell,
foreignInvestorsNetBuySell,
sitcBuy,
sitcSell,
sitcNetBuySell,
dealersProprietaryBuy,
dealersProprietarySell,
dealersProprietaryNetBuySell,
dealersHedgeBuy,
dealersHedgeSell,
dealersHedgeNetBuySell,
dealersBuy,
dealersSell,
dealersNetBuySell,
};
}
}
在 fetchInstInvestorsTrades()
方法中,需要指定 date
參數,表示要取得三大法人買賣金額的日期。我們定義回傳的物件格式如下:
date
:日期foreignDealersExcludedBuy
:外資及陸資(不含外資自營商)買進金額foreignDealersExcludedSell
:外資及陸資(不含外資自營商)賣出金額foreignDealersExcludedNetBuySell
:外資及陸資(不含外資自營商)買賣超foreignDealersBuy
:外資自營商買進金額foreignDealersSell
:外資自營商賣出金額foreignDealersNetBuySell
:外資自營商買賣超foreignInvestorsBuy
:外資合計買進金額foreignInvestorsSell
:外資合計賣出金額foreignInvestorsNetBuySell
:外資合計買賣超sitcBuy
:投信買進金額sitcSell
:投信賣出金額sitcNetBuySell
:投信買賣超dealersProprietaryBuy
:自營商(自行買賣)買進金額dealersProprietarySell
:自營商(自行買賣)賣出金額dealersProprietaryNetBuySell
:自營商(自行買賣)買賣超dealersHedgeBuy
:自營商(避險)買進金額dealersHedgeSell
:自營商(避險)賣出金額dealersHedgeNetBuySell
:自營商(避險)買賣超dealersBuy
:自營商合計買進金額dealersSell
:自營商合計賣出金額dealersNetBuySell
:自營商合計買賣超完成後,我們只要呼叫 TpexScraperService
的 fetchInstInvestorsTrades()
方法,就可以按日期取得櫃買市場三大法人買賣金額。以日期 2022-07-01
為例:
{
date: '2022-07-01',
foreignDealersExcludedBuy: 17118561407,
foreignDealersExcludedSell: 15962798357,
foreignDealersExcludedNetBuySell: 1155763050,
foreignDealersBuy: 0,
foreignDealersSell: 0,
foreignDealersNetBuySell: 0,
foreignInvestorsBuy: 17118561407,
foreignInvestorsSell: 15962798357,
foreignInvestorsNetBuySell: 1155763050,
sitcBuy: 415300400,
sitcSell: 1524110550,
sitcNetBuySell: -1108810150,
dealersProprietaryBuy: 597195811,
dealersProprietarySell: 961369837,
dealersProprietaryNetBuySell: -364174026,
dealersHedgeBuy: 431200169,
dealersHedgeSell: 537928624,
dealersHedgeNetBuySell: -106728455,
dealersBuy: 1028395980,
dealersSell: 1499298461,
dealersNetBuySell: -470902481
}
本系列文已正式出版為《Node.js 量化投資全攻略:從資料收集到自動化交易系統建構實戰》。本書新增了全新內容和實用範例,為你提供更深入的學習體驗!歡迎參考選購,開始你的量化投資之旅!
天瓏網路書店連結:https://www.tenlong.com.tw/products/9786263336070